package com.aysafety.eventmodel.service.microseism.impl;

import com.aysafety.eventmodel.common.DateUtils;
import com.aysafety.eventmodel.common.PythonAlgorithmUtils;
import com.aysafety.eventmodel.dao.MicroseismDao;
import com.aysafety.eventmodel.dao.TreeDao;
import com.aysafety.eventmodel.service.microseism.MicroseismService;
import com.safety.algorithm.eigenvalue.EigenvalueAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.*;

/**
 * @program: iotDataPlatform
 * @description: 微震实现类
 * @author: ChengQi
 * @create: 2019-02-15 14:09
 **/
@Service
public class MicroseismServiceImpl implements MicroseismService {

    @Autowired
    TreeDao treeDao;
    @Autowired
    MicroseismDao microseismDao;
    @Autowired
    PythonAlgorithmUtils pythonAlgorithmUtils;


    // 删除ArrayList中重复元素，保持顺序
    public static List<Map<String, Object>> removeDuplicateWithOrder(List<Map<String, Object>> list) {
        Set<Map<String, Object>> set = new HashSet<Map<String, Object>>();
        List<Map<String, Object>> newList = new ArrayList<Map<String, Object>>();
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> map = new HashMap<String, Object>(2);
            map.put("entId", list.get(i).get("entId"));
            if (set.add(map)) {
                newList.add(map);
            }
        }
        return newList;
    }

    @Override
    public void frequency(String currentTime) throws Throwable {
        // 前一天
        currentTime = DateUtils.getBeforeDayDate(-1, currentTime, "yyyy-MM-dd HH:mm:ss");
        String startTime = DateUtils.getCurrentStartTime("yyyy-MM-dd HH:mm:ss", currentTime);
        String endTime = DateUtils.getCurrentEndTime("yyyy-MM-dd HH:mm:ss", currentTime);

        Map<String, Object> treeMap = new HashMap<String, Object>(1);
        treeMap.put("type", "\'" + "Microseism" + "\'");
        // 树
        List<Map<String, Object>> tree = removeDuplicateWithOrder(treeDao.queryTreeData(treeMap));
        for (Map<String, Object> map : tree) {
            String entId = map.get("entId").toString();
            long sTime = DateUtils.fomatDateTime(startTime).getTime();
            long eTime = DateUtils.fomatDateTime(endTime).getTime();
            Map<String, Object> parram = new HashMap<String, Object>();
            parram.put("tableId", entId + "." + "MICROSEISMREALTIME");
            parram.put("startTime", "\'" + sTime + "\'");
            parram.put("endTime", "\'" + eTime + "\'");
            List<Map<String, Object>> realList = microseismDao.queryRealMicroseism(parram);
            Map<String, Object> result = EigenvalueAlgorithm.microseismEveryday(realList, startTime.substring(0, 10));
            //频次
            int frequency = Integer.parseInt(result.get("frequency").toString());
            //日总
            double totalEnergy = Double.parseDouble(result.get("sum").toString());
            //日最高
            double maxEnergy = Double.parseDouble(result.get("max").toString());
            //日均
            double avgEnergy = Double.parseDouble(result.get("average").toString());
            //频次偏差值
            //查询2次大能量事件中所有事件数量：D_p=(当天微震事件-平均频次)/平均频次
            //获取系统参数
            parram.put("tableId", "sysParameter");
            parram.put("pk", "\'" + entId + ".Microseism" + "\'");
            parram.put("type", "\'" + "Microseism" + "\'");
            Map<String, Object> sysParameter = microseismDao.querySys(parram);

            parram.put("tableId", entId + "." + "MICROSEISMREALTIME");
            parram.remove("startTime");
            parram.put("emergoa", sysParameter.get("LARGEENERGY"));
            parram.put("size", 2);
            List<Map<String, Object>> largeList = microseismDao.queryLarge(parram);
            parram.remove("size");
            double frequencyDeviation = 0;
            if (largeList.size() == 2) {
                sTime = (long) largeList.get(1).get("datetime");
                eTime = (long) largeList.get(0).get("datetime");
                parram.put("startTime", "\'" + sTime + "\'");
                parram.put("endTime", "\'" + eTime + "\'");
                int count = microseismDao.countBetweenLarge(parram);
                //计算每天平均值
                long days = DateUtils.getDaySub(DateUtils
                                .getCurrentStartTime("yyyy-MM-dd HH:mm:ss", DateUtils.getTime(DateUtils.fomatDateTime(sTime))),
                        DateUtils
                                .getCurrentEndTime("yyyy-MM-dd HH:mm:ss", DateUtils.getTime(DateUtils.fomatDateTime(eTime))));
                //频次偏差值
                frequencyDeviation =
                        EigenvalueAlgorithm.divide(frequency, EigenvalueAlgorithm.divide(count, days, 0), 0);
            }
            Map<String, Object> resultMap = new HashMap<String, Object>();
            resultMap.put("pk", "\'" + DateUtils.fomatDateTime(startTime).getTime() + "\'");
            resultMap.put("entId", "\'" + entId + "\'");
            resultMap.put("datetime", DateUtils.fomatDateTime(startTime).getTime());
            resultMap.put("frequency", frequency);
            resultMap.put("totalEnergy", totalEnergy);
            resultMap.put("maxEnergy", maxEnergy);
            resultMap.put("avgEnergy", avgEnergy);
            resultMap.put("frequencyDeviation", frequencyDeviation);
            resultMap.put("tableId", entId + "." + "CalFrequency");
            microseismDao.saveFrequency(resultMap);
        }
    }

    /**
     * @Description: 能量平均值、频次偏差
     * @Param: [currentTime]
     * @return: void
     * @Author: ChengQi
     * @Date: 2019/3/7
     */
    @Override
    public void task2(String currentTime) throws Exception {
        //[t-1min,t]
        String startTime =
                DateUtils.getCurrentMinuteStartTime("yyyy-MM-dd HH:mm:ss", DateUtils.getBeforeMinuteDate(-10, currentTime));
        String endTime = DateUtils.getCurrentMinuteStartTime("yyyy-MM-dd HH:mm:ss", currentTime);

        Map<String, Object> treeMap = new HashMap<String, Object>(1);
        treeMap.put("type", "\'" + "Microseism" + "\'");
        // 树
        List<Map<String, Object>> tree = removeDuplicateWithOrder(treeDao.queryTreeData(treeMap));
        for (Map<String, Object> treeData : tree) {
            String entId = treeData.get("entId").toString();
            long sTime = DateUtils.fomatDateTime(startTime).getTime();
            long eTime = DateUtils.fomatDateTime(endTime).getTime();
            Map<String, Object> parram = new HashMap<String, Object>();
            parram.put("tableId", entId + "." + "MICROSEISMREALTIME");
            parram.put("startTime", "\'" + sTime + "\'");
            parram.put("endTime", "\'" + eTime + "\'");
            List<Map<String, Object>> datas = microseismDao.queryRealMicroseism(parram);

            //获取系统参数
            //D_E=(这一刻实时能量-平均能量)/平均能量
            parram.put("tableId", "sysParameter");
            parram.put("pk", "\'" + entId + ".Microseism" + "\'");
            parram.put("type", "\'" + "Microseism" + "\'");
            Map<String, Object> sysParameter = microseismDao.querySys(parram);

            for (int i = 0; i < datas.size(); i++) {
                /************************************能量偏差值************************************/
                Map<String, Object> map = datas.get(i);
                eTime = (long) map.get("datetime");
                //这一刻实时能量
                double emergoa = Double.parseDouble(map.get("emergoa").toString());
                //查找2次大能量
                parram.put("tableId", entId + "." + "MICROSEISMREALTIME");
                parram.remove("startTime");
                parram.put("endTime", "\'" + eTime + "\'");
                parram.put("emergoa", sysParameter.get("LARGEENERGY"));
                parram.put("size", 2);
                List<Map<String, Object>> largeList = microseismDao.queryLarge(parram);
                parram.remove("size");
                parram.remove("emergoa");
                //能量偏差值
                double D_E = 0.0;
                if (largeList.size() == 2) {
                    long stime = (long) largeList.get(1).get("datetime");
                    long etime = (long) largeList.get(0).get("datetime");
                    parram.put("startTime", "\'" + stime + "\'");
                    parram.put("endTime", "\'" + etime + "\'");
                    //两次大能量矿震事件之间平均每次微震事件的能量
                    double avgEmergoa = microseismDao.avgBetweenLarge(parram);
                    D_E = EigenvalueAlgorithm.divide(emergoa - avgEmergoa, avgEmergoa, 0);
                }
                double frequencyRatio = 0.0;
                /************************************频次比************************************/
                //频次比=前第8、7、6、5、1小时平均频次/前2天平均频次
                sTime = eTime - 2 * 24 * 60 * 60 * 1000;
                parram.put("startTime", "\'" + sTime + "\'");
                parram.put("endTime", "\'" + eTime + "\'");
                //取出前2天实时数据
                List<Map<String, Object>> allList = microseismDao.queryRealMicroseism(parram);
                for (int j = 0; j < allList.size(); j++) {
                    long timestamp = (long) allList.get(j).get("datetime");
                    Date dateTime = DateUtils.fomatDateTime(timestamp);
                    allList.get(j).put("datetime", DateUtils.getTime(dateTime));
                }
                frequencyRatio = countFrequencyPer(allList, DateUtils.getTime(DateUtils.fomatDateTime(eTime)));
                Map<String, Object> resultMap = new HashMap<String, Object>();
                resultMap.put("pk", "\'" + eTime + "\'");
                resultMap.put("entId", "\'" + entId + "\'");
                resultMap.put("datetime", eTime);
                resultMap.put("energyDeviation", D_E);
                resultMap.put("frequencyRatio", frequencyRatio);
                resultMap.put("tableId", entId + "." + "CalMicroseism");
                microseismDao.saveCalfrequencyRatioAndEnergyDeviation(resultMap);
            }
        }

    }

    /**
     * @Description: 离散度
     * @Param: [currentTime]
     * @return: void
     * @Author: ChengQi
     * @Date: 2019/3/8
     */
    @Override
    public void dispersion(String currentTime) throws Exception {
        //[t-1min,t]
        String startTime =
                DateUtils.getCurrentMinuteStartTime("yyyy-MM-dd HH:mm:ss", DateUtils.getBeforeMinuteDate(-60, currentTime));
        String endTime = DateUtils.getCurrentMinuteStartTime("yyyy-MM-dd HH:mm:ss", currentTime);

        Map<String, Object> treeMap = new HashMap<String, Object>(1);
        treeMap.put("type", "\'" + "Microseism" + "\'");
        // 树
        List<Map<String, Object>> tree = removeDuplicateWithOrder(treeDao.queryTreeData(treeMap));
        for (Map<String, Object> treeData : tree) {
            String entId = treeData.get("entId").toString();
            Map<String, Object> parram = new HashMap<String, Object>();
            parram.put("tableId", entId + "." + "MICROSEISMREALTIME");
            parram.put("startTime", "\'" + DateUtils.fomatDateTime(startTime).getTime() + "\'");
            parram.put("endTime", "\'" + DateUtils.fomatDateTime(endTime).getTime() + "\'");
            //1小时内所有微震事件
            List<Map<String, Object>> datas = microseismDao.queryRealMicroseism(parram);

            loop:
            for (int i = 0; i < datas.size(); i++) {
                /**********************************1.计算特征能量**********************************************/
                //特征能量=最大能量+中位数能量
                Map<String, Object> map = datas.get(i);
                long eTime = (long) map.get("datetime");
                long sTime = eTime - 8 * 60 * 60 * 1000;
                parram.put("startTime", "\'" + sTime + "\'");
                parram.put("endTime", "\'" + eTime + "\'");
                //每条数据向前查询8小时数据
                List<Map<String, Object>> realList = microseismDao.queryRealMicroseismByEmergoa(parram);
                if (realList.size() == 1) {
                    Map<String, Object> resultMap = new HashMap<String, Object>();
                    resultMap.put("tableId", entId + "." + "calDispersion");
                    resultMap.put("pk", "\'" + realList.get(0).get("datetime") + "\'");
                    resultMap.put("entId", "\'" + entId + "\'");
                    resultMap.put("datetime", realList.get(0).get("datetime"));
                    resultMap.put("w", realList.get(0).get("emergoa"));
                    resultMap.put("d", 0);
                    resultMap.put("characteristicEnergy", realList.get(0).get("emergoa"));
                    resultMap.put("dispersion", 2);
                    microseismDao.saveDispersion(resultMap);
                    continue loop;
                }


                //特征能量
                double characteristicEnergy = 0.0;
                //中位数能量
                double median = 0.0;
                //最大能量
                double max = 0.0;
                /******************加权平均距离计算参数********************/
                //x的平均值
                double avgx = 0.0;
                //y的平均值
                double avgy = 0.0;
                //z的平均值
                double avgz = 0.0;
                double sumXW = 0;
                double sumYW = 0;
                double sumZW = 0;
                double sumW = 0;

                for (int j = 0; j < realList.size(); j++) {
                    Map<String, Object> data = realList.get(j);
                    double w = Double.parseDouble(data.get("emergoa").toString());
                    double x = Double.parseDouble(data.get("x").toString());
                    double y = Double.parseDouble(data.get("y").toString());
                    double z = Double.parseDouble(data.get("z").toString());
                    max = w > max ? w : max;
                    sumXW += x * w;
                    sumYW += y * w;
                    sumZW += z * w;
                    sumW += w;
                }
                avgx = EigenvalueAlgorithm.divide(sumXW, sumW, 0);
                avgy = EigenvalueAlgorithm.divide(sumYW, sumW, 0);
                avgz = EigenvalueAlgorithm.divide(sumZW, sumW, 0);
                /*******************************************************/

                if (realList.size() > 0) {
                    median = Double.parseDouble(realList.get(realList.size() / 2).get("emergoa").toString());
                }
                //特征能量
                characteristicEnergy = max + median;

                //用于存放加权平均距离
                List<Map<String, Object>> dList = new ArrayList<>();
                double wi = 0.0;
                /**********************************2.计算临界特征能量**********************************************/
                for (int j = 0; j < realList.size(); j++) {
                    Map<String, Object> data = realList.get(j);
                    double w = Double.parseDouble(data.get("emergoa").toString());
                    double x = Double.parseDouble(data.get("x").toString());
                    double y = Double.parseDouble(data.get("y").toString());
                    double z = Double.parseDouble(data.get("z").toString());
                    long datetime = (long) data.get("datetime");
                    wi += w;
                    double d = 0.0;
                    double a = EigenvalueAlgorithm.divide(Math.pow((x - avgx), 2) * w, wi, 0);
                    double b = EigenvalueAlgorithm.divide(Math.pow((y - avgy), 2) * w, wi, 0);
                    double c = EigenvalueAlgorithm.divide(Math.pow((z - avgz), 2) * w, wi, 0);
                    d = Math.sqrt(a + b + c);
                    Map<String, Object> subMap = new HashMap<String, Object>(3);
                    subMap.put("datetime", datetime);
                    subMap.put("d", d);
                    subMap.put("w", w);
                    dList.add(subMap);
                }
                //对计算好的加权平均距离由大到小进行排序
                Collections.sort(dList, new Comparator<Map<String, Object>>() {
                    @Override
                    public int compare(Map<String, Object> map1, Map<String, Object> map2) {
                        Double d1 = Double.parseDouble(map1.get("d").toString());
                        Double d2 = Double.parseDouble(map2.get("d").toString());
                        return d1.compareTo(d2);
                    }
                });
                System.out.println(dList);
                //找出其中位于1.2%，7.04%，27.5%，80.84%，88.51%，94.84%，98.34%,找到这7组数据
                Map<String, Object> map1 = dList.get((int) Math.floor(dList.size() * 0.012));
                double d1 = Double.parseDouble(map1.get("d").toString());
                Map<String, Object> map2 = dList.get((int) Math.floor(dList.size() * 0.0704));
                double d2 = Double.parseDouble(map2.get("d").toString());
                Map<String, Object> map3 = dList.get((int) Math.floor(dList.size() * 0.275));
                double d3 = Double.parseDouble(map3.get("d").toString());
                Map<String, Object> map4 = dList.get((int) Math.floor(dList.size() * 0.8084));
                double d4 = Double.parseDouble(map4.get("d").toString());
                Map<String, Object> map5 = dList.get((int) Math.floor(dList.size() * 0.8851));
                double d5 = Double.parseDouble(map5.get("d").toString());
                Map<String, Object> map6 = dList.get((int) Math.floor(dList.size() * 0.9484));
                double d6 = Double.parseDouble(map6.get("d").toString());
                Map<String, Object> map7 = dList.get((int) Math.floor(dList.size() * 0.9834));
                double d7 = Double.parseDouble(map7.get("d").toString());

                List<Map<String, Object>> d1List = new ArrayList<>();
                List<Map<String, Object>> d2List = new ArrayList<>();
                List<Map<String, Object>> d3List = new ArrayList<>();
                List<Map<String, Object>> d4List = new ArrayList<>();
                List<Map<String, Object>> d5List = new ArrayList<>();
                List<Map<String, Object>> d6List = new ArrayList<>();
                List<Map<String, Object>> d7List = new ArrayList<>();
                //将上述得到的7个加权平均距离左右半径一米内的所有特征能量点分别按从小到大的顺序排列
                for (int j = 0; j < dList.size(); j++) {
                    Map<String, Object> subMap = dList.get(j);
                    double d = Double.parseDouble(subMap.get("d").toString());
                    if (d >= (d1 - 1) && d <= (d1 + 1)) {
                        d1List.add(subMap);
                    } else if (d >= (d2 - 1) && d <= (d2 + 1)) {
                        d2List.add(subMap);
                    } else if (d >= (d3 - 1) && d <= (d3 + 1)) {
                        d3List.add(subMap);
                    } else if (d >= (d4 - 1) && d <= (d4 + 1)) {
                        d4List.add(subMap);
                    } else if (d >= (d5 - 1) && d <= (d5 + 1)) {
                        d5List.add(subMap);
                    } else if (d >= (d6 - 1) && d <= (d6 + 1)) {
                        d6List.add(subMap);
                    } else if (d >= (d7 - 1) && d <= (d7 + 1)) {
                        d7List.add(subMap);
                    }
                }
                if (d1List.size() == 0) {
                    d1List.add(map1);
                }
                if (d2List.size() == 0) {
                    d2List.add(map2);
                }
                if (d3List.size() == 0) {
                    d3List.add(map3);
                }
                if (d4List.size() == 0) {
                    d4List.add(map4);
                }
                if (d5List.size() == 0) {
                    d5List.add(map5);
                }
                if (d6List.size() == 0) {
                    d6List.add(map6);
                }
                if (d7List.size() == 0) {
                    d7List.add(map7);
                }

                //将上述得到的7个集合，按能量大小排序
                Collections.sort(d1List, new Comparator<Map<String, Object>>() {
                    @Override
                    public int compare(Map<String, Object> map1, Map<String, Object> map2) {
                        Double w1 = Double.parseDouble(map1.get("w").toString());
                        Double w2 = Double.parseDouble(map2.get("w").toString());
                        return w1.compareTo(w2);
                    }
                });
                Collections.sort(d2List, new Comparator<Map<String, Object>>() {
                    @Override
                    public int compare(Map<String, Object> map1, Map<String, Object> map2) {
                        Double w1 = Double.parseDouble(map1.get("w").toString());
                        Double w2 = Double.parseDouble(map2.get("w").toString());
                        return w1.compareTo(w2);
                    }
                });
                Collections.sort(d3List, new Comparator<Map<String, Object>>() {
                    @Override
                    public int compare(Map<String, Object> map1, Map<String, Object> map2) {
                        Double w1 = Double.parseDouble(map1.get("w").toString());
                        Double w2 = Double.parseDouble(map2.get("w").toString());
                        return w1.compareTo(w2);
                    }
                });
                Collections.sort(d4List, new Comparator<Map<String, Object>>() {
                    @Override
                    public int compare(Map<String, Object> map1, Map<String, Object> map2) {
                        Double w1 = Double.parseDouble(map1.get("w").toString());
                        Double w2 = Double.parseDouble(map2.get("w").toString());
                        return w1.compareTo(w2);
                    }
                });
                Collections.sort(d5List, new Comparator<Map<String, Object>>() {
                    @Override
                    public int compare(Map<String, Object> map1, Map<String, Object> map2) {
                        Double w1 = Double.parseDouble(map1.get("w").toString());
                        Double w2 = Double.parseDouble(map2.get("w").toString());
                        return w1.compareTo(w2);
                    }
                });
                Collections.sort(d6List, new Comparator<Map<String, Object>>() {
                    @Override
                    public int compare(Map<String, Object> map1, Map<String, Object> map2) {
                        Double w1 = Double.parseDouble(map1.get("w").toString());
                        Double w2 = Double.parseDouble(map2.get("w").toString());
                        return w1.compareTo(w2);
                    }
                });
                Collections.sort(d7List, new Comparator<Map<String, Object>>() {
                    @Override
                    public int compare(Map<String, Object> map1, Map<String, Object> map2) {
                        Double w1 = Double.parseDouble(map1.get("w").toString());
                        Double w2 = Double.parseDouble(map2.get("w").toString());
                        return w1.compareTo(w2);
                    }
                });

                //将每个加权平均距离周围的特征能量点分别取（40%-45%），（45%-50%），
                // （98%-99%），（98%-99%），（98%-99%），（90%-98%），（85%-90%）范围内的点，
                //（40%-45%）
                List<Map<String, Object>> d1SubList = new ArrayList<Map<String, Object>>();
                if (d1List.size() > 0) {
                    //size=1,[0.4,0.9)取0
                    if (Math.floor(d1List.size() * 0.45) - Math.floor(d1List.size() * 0.4) > 1) {
                        d1SubList = d1List
                                .subList((int) Math.floor(d1List.size() * 0.4), (int) Math.floor(d1List.size() * 0.45));
                    } else {
                        d1SubList.add(d1List.get((int) Math.floor(d1List.size() * 0.4)));
                    }
                } else {
                    d1SubList.add(map1);
                }

                //（45%-50%）
                List<Map<String, Object>> d2SubList = new ArrayList<Map<String, Object>>();
                if (d2List.size() > 0) {
                    if ((Math.floor(d2List.size() * 0.5) - Math.floor(d2List.size() * 0.45)) > 1) {
                        d2SubList = d2List
                                .subList((int) Math.floor(d2List.size() * 0.45), (int) Math.floor(d2List.size() * 0.5));
                    } else {
                        d2SubList.add(d2List.get((int) Math.floor(d2List.size() * 0.45)));
                    }
                } else {
                    d2SubList.add(map2);
                }

                //（98%-99%）
                List<Map<String, Object>> d3SubList = new ArrayList<Map<String, Object>>();
                if (d3List.size() > 0) {

                    if ((Math.floor(d3List.size() * 0.99) - Math.floor(d3List.size() * 0.98)) > 1) {
                        d3SubList = d3List
                                .subList((int) Math.floor(d3List.size() * 0.98), (int) Math.floor(d3List.size() * 0.99));
                    } else {
                        d3SubList.add(d3List.get((int) Math.floor(d3List.size() * 0.98)));
                    }

                } else {
                    d3SubList.add(map3);
                }

                //（98%-99%）
                List<Map<String, Object>> d4SubList = new ArrayList<Map<String, Object>>();
                if (d4List.size() > 0) {
                    if ((Math.floor(d4List.size() * 0.99) - Math.floor(d4List.size() * 0.98)) > 1) {
                        d4SubList = d4List
                                .subList((int) Math.floor(d4List.size() * 0.98), (int) Math.floor(d4List.size() * 0.99));
                    } else {
                        d4SubList.add(d4List.get((int) Math.floor(d4List.size() * 0.98)));
                    }
                } else {
                    d4SubList.add(map4);
                }

                //（98%-99%）
                List<Map<String, Object>> d5SubList = new ArrayList<Map<String, Object>>();
                if (d5List.size() > 0) {

                    if ((Math.floor(d5List.size() * 0.99) - Math.floor(d5List.size() * 0.98)) > 1) {
                        d5SubList = d5List
                                .subList((int) Math.floor(d5List.size() * 0.98), (int) Math.floor(d5List.size() * 0.99));
                    } else {
                        d5SubList.add(d5List.get((int) Math.floor(d5List.size() * 0.98)));
                    }
                } else {
                    d5SubList.add(map5);
                }

                //（90%-98%）
                List<Map<String, Object>> d6SubList = new ArrayList<Map<String, Object>>();
                if (d6List.size() > 0) {
                    if ((Math.floor(d6List.size() * 0.98) - Math.floor(d6List.size() * 0.90)) > 1) {
                        d6SubList = d6List
                                .subList((int) Math.floor(d6List.size() * 0.90), (int) Math.floor(d6List.size() * 0.98));
                    } else {
                        d6SubList.add(d6List.get((int) Math.floor(d6List.size() * 0.90)));
                    }
                } else {
                    d6SubList.add(map6);
                }

                //（85%-90%）
                List<Map<String, Object>> d7SubList = new ArrayList<Map<String, Object>>();
                if (d7List.size() > 0) {
                    if ((Math.floor(d7List.size() * 0.90) - Math.floor(d7List.size() * 0.85)) > 1) {
                        d7SubList = d7List
                                .subList((int) Math.floor(d7List.size() * 0.85), (int) Math.floor(d7List.size() * 0.90));
                    } else {
                        d7SubList.add(d7List.get((int) Math.floor(d7List.size() * 0.85)));
                    }
                } else {
                    d7SubList.add(map7);
                }
                //取每个范围内所有特征能量的平均值得到平均特征能量点
                double sum1 = 0.0;
                double avg1 = 0.0;
                for (int j = 0; j < d1SubList.size(); j++) {
                    Map<String, Object> subMap = d1SubList.get(j);
                    sum1 += Double.parseDouble(subMap.get("w").toString());
                }
                avg1 = EigenvalueAlgorithm.divide(sum1, d1SubList.size(), 0);
                double sum2 = 0.0;
                double avg2 = 0.0;
                for (int j = 0; j < d2SubList.size(); j++) {
                    Map<String, Object> subMap = d2SubList.get(j);
                    sum2 += Double.parseDouble(subMap.get("w").toString());
                }
                avg2 = EigenvalueAlgorithm.divide(sum2, d2SubList.size(), 0);
                double sum3 = 0.0;
                double avg3 = 0.0;
                for (int j = 0; j < d3SubList.size(); j++) {
                    Map<String, Object> subMap = d3SubList.get(j);
                    sum3 += Double.parseDouble(subMap.get("w").toString());
                }
                avg3 = EigenvalueAlgorithm.divide(sum3, d3SubList.size(), 0);
                double sum4 = 0.0;
                double avg4 = 0.0;
                for (int j = 0; j < d4SubList.size(); j++) {
                    Map<String, Object> subMap = d4SubList.get(j);
                    sum4 += Double.parseDouble(subMap.get("w").toString());
                }
                avg4 = EigenvalueAlgorithm.divide(sum4, d4SubList.size(), 0);
                double sum5 = 0.0;
                double avg5 = 0.0;
                for (int j = 0; j < d5SubList.size(); j++) {
                    Map<String, Object> subMap = d5SubList.get(j);
                    sum5 += Double.parseDouble(subMap.get("w").toString());
                }
                avg5 = EigenvalueAlgorithm.divide(sum5, d5SubList.size(), 0);
                double sum6 = 0.0;
                double avg6 = 0.0;
                for (int j = 0; j < d6SubList.size(); j++) {
                    Map<String, Object> subMap = d6SubList.get(j);
                    sum6 += Double.parseDouble(subMap.get("w").toString());
                }
                avg6 = EigenvalueAlgorithm.divide(sum6, d6SubList.size(), 0);
                double sum7 = 0.0;
                double avg7 = 0.0;
                for (int j = 0; j < d7SubList.size(); j++) {
                    Map<String, Object> subMap = d7SubList.get(j);
                    sum7 += Double.parseDouble(subMap.get("w").toString());
                }
                avg7 = EigenvalueAlgorithm.divide(sum7, d7SubList.size(), 0);
                //得到7个点，d为横轴，临界特征能量为纵轴，代入插值法
                double finalAvg1 = avg1;
                double finalAvg2 = avg2;
                double finalAvg3 = avg3;
                double finalAvg4 = avg4;
                double finalAvg5 = avg5;
                double finalAvg6 = avg6;
                double finalAvg7 = avg7;
                List<Object> seven = new ArrayList<Object>() {{
                    List<Object> sublist = new ArrayList<Object>();
                    sublist.add(d1);
                    sublist.add(finalAvg1);
                    add(sublist);
                    sublist = new ArrayList<Object>();
                    sublist.add(d2);
                    sublist.add(finalAvg2);
                    add(sublist);
                    sublist = new ArrayList<Object>();
                    sublist.add(d3);
                    sublist.add(finalAvg3);
                    add(sublist);
                    sublist = new ArrayList<Object>();
                    sublist.add(d4);
                    sublist.add(finalAvg4);
                    add(sublist);
                    sublist = new ArrayList<Object>();
                    sublist.add(d5);
                    sublist.add(finalAvg5);
                    add(sublist);
                    sublist = new ArrayList<Object>();
                    sublist.add(d6);
                    sublist.add(finalAvg6);
                    add(sublist);
                    sublist = new ArrayList<Object>();
                    sublist.add(d7);
                    sublist.add(finalAvg7);
                    add(sublist);
                }};
                List<Object> calculate = new ArrayList<Object>();
                for (int j = 0; j < dList.size(); j++) {
                    calculate.add(dList.get(j).get("d"));
                }
                Map<String, Object> reqMap = new HashMap<String, Object>();
                reqMap.put("seven", seven);
                reqMap.put("calculate", calculate);
                String rsp = pythonAlgorithmUtils.serviceHermite(reqMap);
                String[] ds = rsp.substring(1, rsp.length() - 1).split(",");
                List<Map<String, Object>> newdList = new ArrayList<>();
                for (int j = 0; j < dList.size(); j++) {
                    Map<String, Object> sub = new HashMap<String, Object>();
                    sub.put("w", ds[j]);
                    sub.put("datetime", dList.get(j).get("datetime"));
                    sub.put("d", dList.get(j).get("d"));
                    newdList.add(sub);
                }
                //计算离散度
                for (int j = 0; j < newdList.size(); j++) {
                    Map<String, Object> newSub = newdList.get(j);
                    Map<String, Object> resultMap = new HashMap<String, Object>();
                    resultMap.put("tableId", entId + "." + "calDispersion");
                    resultMap.put("pk", "\'" + newSub.get("datetime") + "\'");
                    resultMap.put("entId", "\'" + entId + "\'");
                    resultMap.put("datetime", newSub.get("datetime"));
                    resultMap.put("w", newSub.get("w"));
                    resultMap.put("d", newSub.get("d"));
                    resultMap.put("characteristicEnergy", characteristicEnergy);
                    double a = EigenvalueAlgorithm
                            .divide(Double.parseDouble(newSub.get("w").toString()), characteristicEnergy, 1);
                    resultMap.put("dispersion", a > 0 ? Math.log10(a) : -Math.log10(-a));
                    microseismDao.saveDispersion(resultMap);
                }
            }
        }
    }

    @Override
    public void warning(String currentTime) throws Exception {
/*
        //[t-1min,t]
        String startTime =
                DateUtils.getCurrentMinuteStartTime("yyyy-MM-dd HH:mm:ss", DateUtils.getBeforeMinuteDate(-10, currentTime));
        String endTime = DateUtils.getCurrentMinuteStartTime("yyyy-MM-dd HH:mm:ss", currentTime);

        Map<String, Object> treeMap = new HashMap<String, Object>(1);
        treeMap.put("type", "\'" + "Microseism" + "\'");
        // 树
        List<Map<String, Object>> tree = removeDuplicateWithOrder(treeDao.queryTreeData(treeMap));
        for (Map<String, Object> treeData : tree) {
            String entId = treeData.get("entId").toString();
            long sTime = DateUtils.fomatDateTime(startTime).getTime();
            long eTime = DateUtils.fomatDateTime(endTime).getTime();
            Map<String, Object> parram = new HashMap<String, Object>();
            parram.put("tableId", entId + "." + "MICROSEISMREALTIME");
            parram.put("startTime", "\'" + sTime + "\'");
            parram.put("endTime", "\'" + eTime + "\'");
            List<Map<String, Object>> datas = microseismDao.queryRealMicroseism(parram);

            //查询学习出来的临界值
            parram.put("tableId", "MicroseismWarningStudy");
            parram.put("pk", "\'" + entId + "\'");
            Map<String, Object> studyInfo = microseismDao.queryMicroseismWarningStudy(parram);
            double best1 = Double.parseDouble(studyInfo.get("best1").toString());
            double best2 = Double.parseDouble(studyInfo.get("best2").toString());
            double best3 = Double.parseDouble(studyInfo.get("best3").toString());
            double best4 = Double.parseDouble(studyInfo.get("best4").toString());
            double best5 = Double.parseDouble(studyInfo.get("best5").toString());
            double best6 = Double.parseDouble(studyInfo.get("best6").toString());
            double R1 = Double.parseDouble(studyInfo.get("R1").toString());
            double R2 = Double.parseDouble(studyInfo.get("R2").toString());

            for (int i = 0; i < datas.size(); i++) {
                //查询前8小时数据，判断maxW
                double emergoa = Double.parseDouble(datas.get(i).get("emergoa").toString());
                long etime = (long) datas.get(i).get("datetime");
                long stime = etime;
                parram.put("endTime", "\'" + etime + "\'");
                parram.put("startTime", "\'" + stime + "\'");
                int w3 = 0;
                int w4 = 0;
                //频次比
                parram.put("tableId", entId + "." + "CalMicroseism");
                List<Double> cList3 = microseismDao.queryEnergyDeviation1(parram);
                //离散度
                parram.put("tableId", entId + "." + "calDispersion");
                List<Double> cList4 = microseismDao.queryDispersion1(parram);
                if (cList3.size() != 1 || cList4.size() != 1) {
                    //实时能量未计算
                    continue;
                } else {
                    if (emergoa > best1) {
                        w3++;
                    }
                    if (cList3.get(0) > best2) {
                        w3++;
                    }
                    if (cList4.get(0) > best3) {
                        w3++;
                    }
                    if (emergoa > best4) {
                        w4++;
                    }
                    if (cList3.get(0) > best5) {
                        w4++;
                    }
                    if (cList4.get(0) > best6) {
                        w4++;
                    }
                }

                etime = (long) datas.get(i).get("datetime");
                stime = etime - 8 * 60 * 60 * 1000;
                parram.put("endTime", "\'" + etime + "\'");
                parram.put("startTime", "\'" + stime + "\'");
                //实时能量
                parram.put("tableId", entId + "." + "MICROSEISMREALTIME");
                List<Map<String, Object>> realList = microseismDao.queryRealMicroseism(parram);
                List<Double> eList = new LinkedList<Double>();
                for (int j = 0; j < realList.size(); j++) {
                    eList.add(Double.parseDouble(realList.get(j).get("emergoa").toString()));
                }

                //频次比
                parram.put("tableId", entId + "." + "CalMicroseism");
                parram.put("flag", 1);
                List<Double> cList1 = microseismDao.queryEnergyDeviation1(parram);
                //离散度
                parram.put("tableId", entId + "." + "calDispersion");
                List<Double> cList2 = microseismDao.queryDispersion1(parram);
                parram.remove("flag");
                int w1 = 0;
                int w2 = 0;
                int maxw = 0;

                for (int j = 0; j < eList.size(); j++) {
                    if (eList.get(j) > best1) {
                        w1++;
                    }
                    if (cList1.get(j) > best2) {
                        w1++;
                    }
                    if (cList2.get(j) > best3) {
                        w1++;
                    }
                    if (eList.get(j) > best4) {
                        w2++;
                    }
                    if (cList1.get(j) > best5) {
                        w2++;
                    }
                    if (cList2.get(j) > best6) {
                        w2++;
                    }

                    maxw = maxw > (w1 > w2 ? w1 : w2) ? maxw : (w1 > w2 ? w1 : w2);
                    w1 = 0;
                    w2 = 0;
                }

                //计算W综
                double wz = EigenvalueAlgorithm.divide((w3 * R1 + w4 * R2), maxw * (R1 + R2), 0);
                Map<String, Object> resultMap = new HashMap<String, Object>();
                resultMap.put("tableId", entId + "." + "MicroseismWarning");
                resultMap.put("pk", "\'" + etime + "\'");
                resultMap.put("datetime", etime);
                resultMap.put("w", wz);
                microseismDao.saveWarning(resultMap);
            }
        }
*/
    }

    private double countFrequencyPer(List<Map<String, Object>> allList, String largeEndTime) throws Exception {

        int frequency1H = 0;
        int frequency5H = 0;
        int frequency6H = 0;
        int frequency7H = 0;
        int frequency8H = 0;
        int frequency2D = 0;
        for (Map<String, Object> data : allList) {
            if (!data.containsKey("datetime")) {
                continue;
            }
            String cDatetime = data.get("datetime").toString();
            //[-1,0]
            if (DateUtils.compareDate(cDatetime, DateUtils.getBeforehourDate(-1, largeEndTime))) {
                frequency1H++;
            }
            //[-5,-4]
            if (DateUtils.compareDate(cDatetime, DateUtils.getBeforehourDate(-5, largeEndTime)) && DateUtils
                    .compareDate(DateUtils.getBeforehourDate(-4, largeEndTime), cDatetime)) {
                frequency5H++;
            }
            //[-6,-5]
            if (DateUtils.compareDate(cDatetime, DateUtils.getBeforehourDate(-6, largeEndTime)) && DateUtils
                    .compareDate(DateUtils.getBeforehourDate(-5, largeEndTime), cDatetime)) {
                frequency6H++;
            }
            //[-7,-6]
            if (DateUtils.compareDate(cDatetime, DateUtils.getBeforehourDate(-7, largeEndTime)) && DateUtils
                    .compareDate(DateUtils.getBeforehourDate(-6, largeEndTime), cDatetime)) {
                frequency7H++;
            }
            //[-8,-7]
            if (DateUtils.compareDate(cDatetime, DateUtils.getBeforehourDate(-8, largeEndTime)) && DateUtils
                    .compareDate(DateUtils.getBeforehourDate(-7, largeEndTime), cDatetime)) {
                frequency8H++;
            }
            frequency2D++;
        }
        double frequencyPer = 0;
        if (frequency2D > 0) {
            frequencyPer = EigenvalueAlgorithm
                    .divide(48 * (frequency1H + frequency5H + frequency6H + frequency5H + frequency7H + frequency8H),
                            frequency2D * 5, 0);
        }
        return frequencyPer;
    }


    /****************************************重写微震综合预警*******************************************************/
    /**
     * @param currentTime
     */
    public void warningV2(String currentTime) throws Exception {
        //[t-1min,t]
        String startTime =
                DateUtils.getCurrentMinuteStartTime("yyyy-MM-dd HH:mm:ss", DateUtils.getBeforeMinuteDate(-10, currentTime));
        String endTime = DateUtils.getCurrentMinuteStartTime("yyyy-MM-dd HH:mm:ss", currentTime);

        // 从历史数据中计算maxW
        if (maxW == 0) {
            init(START_DATETIME, END_DATETIME);
        }

        long sTime = DateUtils.fomatDateTime(startTime).getTime();
        long eTime = DateUtils.fomatDateTime(endTime).getTime();

        Map<String, Object> treeMap = new HashMap<String, Object>(1);
        treeMap.put("type", "\'" + "Microseism" + "\'");

        Map<String, Integer> warningAndW = new HashMap<>();
        long datetime = 0l;
        String entId = "";
        // 树
        List<Map<String, Object>> tree = removeDuplicateWithOrder(treeDao.queryTreeData(treeMap));
        for (Map<String, Object> treeData : tree) {
            entId = treeData.get("entId").toString();

            Map<String, Object> params = new HashMap<>();
            params.put("startTime", sTime);
            params.put("endTime", eTime);

            params.put("tableId", entId + "." + "CalMicroseism");

            // 长预警警报程度w1,短预警警报程度w2
            int w1 = 0, w2 = 0;
            List<Map<String, Object>> frequencyRatioList = microseismDao.queryEnergyDeviation1(params);
            if (frequencyRatioList.size() == 1) {
                Map<String, Object> frequencyRatioMap = frequencyRatioList.get(0);
                double frequencyRatio = (double) frequencyRatioMap.get("frequencyRatio");
                datetime = (long) frequencyRatioMap.get("datetime");
                if (frequencyRatio > warningAndV1.get("longWarning")) {
                    w1++;
                }

                if (frequencyRatio > warningAndV1.get("shortWarning")) {
                    w2++;
                }
            }


            params.put("tableId", entId + "." + "calDispersion");
            List<Map<String, Object>> dispersionList = microseismDao.queryDispersion1(params);
            if (dispersionList.size() == 1) {
                Map<String, Object> dispersionMap = dispersionList.get(0);
                double dispersion = (double) dispersionMap.get("dispersion");
                datetime = (long) dispersionMap.get("datetime");
                if (dispersion > warningAndV2.get("longWarning")) {
                    w1++;
                }

                if (dispersion > warningAndV2.get("shortWarning")) {
                    w2++;
                }
            }


            synchronized (this) { // 加锁，防止线程安全问题
                int longWarningW = warningAndW.get("longWarning");
                int shortWarningW = warningAndW.get("shortWarning");
                maxW = maxW > (longWarningW > shortWarningW ? longWarningW : shortWarningW) ? maxW : (longWarningW > shortWarningW ? longWarningW : shortWarningW);

                // 放入警报程度w1和w2
                warningAndW.put("longWarning", longWarningW);
                warningAndW.put("shortWarning", shortWarningW);


                if (R == 0.0) {
                    params.put("startTime", START_DATETIME);
                    params.put("endTime", END_DATETIME);
                    final List<Map<String, Object>> realMicroseismList = microseismDao.queryRealMicroseism(params);
                    R = computeR(realMicroseismList, entId);
                } else {
                    final List<Map<String, Object>> realMicroseismList = microseismDao.queryRealMicroseism(params);
                    R = computeR(realMicroseismList, entId);
                    //deviceidAndR.put(deviceId, R);
                }
            }
        }

        // 计算预警程度W
        double W = computeW(warningAndW);
        System.out.println("综合预警值w: " + W + " R: " + R + " datetime: " + datetime);
        // 预警结果W和预警能力R存入表中
        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("tableId", entId + "." + "MICROSEISMWARNING");
        resultMap.put("entId", "\'" + entId + "\'");
        resultMap.put("pk", "\'" + datetime + "\'");
        resultMap.put("datetime", datetime);
        resultMap.put("w", W);
        resultMap.put("R", R);
        //microseismDao.saveWarning(resultMap);
    }


    /**
     * 计算综合预警程度
     * @param warningAndW
     * @return
     */
    private double computeW(Map<String, Integer> warningAndW) {
        double result = 0.0;
        double sumR = sumR();
        for (Map.Entry<String, Integer> entry : warningAndW.entrySet()) {
            String rKey = entry.getKey();
            int w = entry.getValue();

            //int maxW = deviceidAndMaxW.get(deviceId);
            double R = warningAndR.get(rKey);
            if (0 == maxW) {
                result = 0.0;
            } else {
                double tempW = w / maxW;
                BigDecimal tempR = new BigDecimal(R).divide(new BigDecimal(sumR), 2, BigDecimal.ROUND_HALF_DOWN);
                result = result + new BigDecimal(tempW).multiply(tempR, new MathContext(2, RoundingMode.HALF_DOWN)).doubleValue();
            }
        }
        return result;
    }

    private double sumR() {
        return longWarningR + shortWarningR;
    }

    /**
     * 报对次数
     */
    private int rightWarningNumber;

    /**
     * 应预警总次数
     */
    private int shouldWarningNumber;

    /**
     * 遗传算法计算出来的预警时间
     */
    private double warningTimes = 0.0;

    private double computeR(List<Map<String, Object>> realMicroseismList, String entId) {
        if (realMicroseismList == null || realMicroseismList.size() == 0) {
            return R;
        }

        for (int i=0; i<realMicroseismList.size(); i++) {
            double emergoa = (double) realMicroseismList.get(i).get("emergoa");
            long datetime = (long) realMicroseismList.get(i).get("datetime");
            if (emergoa > 100000) {
                // 如果前一天内预警程度达到0.5，报对次数加1
                long preDatetime = datetime - 24 * 60 * 1000;
                Map<String, Object> params = new HashMap<>();
                params.put("startTime", preDatetime);
                params.put("endTime", datetime);
                params.put("tableId", entId + "." + "GEOSOUNDWARNING");
                boolean isWarning = false;
                List<Double> warnings = microseismDao.queryMircroseismWarning(params);
                for (int j=0; j<warnings.size(); j++) {
                    if (warnings.get(j) > 0.5) {
                        isWarning = true;
                    }
                }
                if (isWarning) {
                    rightWarningNumber++;
                }
                shouldWarningNumber++;
                // 需要重新计算R,R的计算公式为：R=报对次数/应报警总次数-预警占用时间/预警研究总时间
                // 四舍五入取小数点后两位
                double temp1 = new BigDecimal(rightWarningNumber/shouldWarningNumber, new MathContext(2, RoundingMode.HALF_DOWN)).doubleValue();

                // 预警占用时间=报对次数(预警的次数) * 遗传算法计算出来的预警时长(固定为两天时间，单位为分钟)
                if (0.0 == warningTimes) {
                    warningTimes = rightWarningNumber * (2 * 24 * 60);
                }

                // 预警研究总时间,就是此刻到开始研究的总时间。例如，数据是从2016年开始的，那么预警研究总时间就是此刻到2016年的时间
                BigInteger subtract = BigInteger.valueOf(datetime).subtract(BigInteger.valueOf(Long.parseLong(START_DATETIME)));
                // 四舍五入取小数点后两位
                //double temp2 = new BigDecimal(subtract).divide(new BigDecimal(60000l), 2, BigDecimal.ROUND_HALF_DOWN).doubleValue();
                double temp2 = new BigDecimal(warningTimes).divide(new BigDecimal(subtract), 2, BigDecimal.ROUND_HALF_DOWN).doubleValue();

                R = temp1 - temp2;
            }
        }
        return R;
    }

    /**
     * 预警能力R
     */
    private double R;

    /**
     * 长期预警时间
     */
    private double longWarningTime;

    private double longWarningR;

    /**
     * 短期预警时间
     */
    private double shortWarningTime;

    private double shortWarningR;

    private final Map<String, Double> warningAndR = new HashMap<>();

    /**
     * 2016-01-01 00:00:00的时间戳:1451577600000
     * 2018-01-01 00:00:00的时间戳:1514736000000
     */
    private final String START_DATETIME = "1514736000000";

    /**
     * 2017-01-01 00:00:00的时间戳:1483200000000
     * 2019-01-01 00:00:00的时间戳:1546272000000
     */
    private final String END_DATETIME = "1483200000000";

    private int maxW;

    /**
     * 存放预警特征参V1：频次比
     * String: 长预警(longWarning)还是短预警(shortWarning)
     * Double: 特征参V1
     */
    private final Map<String, Double> warningAndV1 = new HashMap<>();

    /**
     * 存放预警特征参V2：离散度
     * String: 长预警(longWarning)还是短预警(shortWarning)
     * Double: 特征参V2
     */
    private final Map<String, Double> warningAndV2 = new HashMap<>();


    private void init(String startTime, String endTime) {
        Map<String, Object> params = new HashMap<>();
        String entId = "xinjiangwudong";
        params.put("pk", entId);
        Map<String, Object> studyResult = microseismDao.queryMicroseismWarningStudy(params);

        // 初始化成员变量
        initialField(studyResult);

        params.put("startTime", startTime);
        params.put("endTime", endTime);
        // 频次比
        params.put("tableId", entId + "." + "CalMicroseism");
        List<Map<String, Object>> frequencyRatioList = microseismDao.queryEnergyDeviation1(params);
        // 离散度
        params.put("tableId", entId + "." + "calDispersion");
        List<Map<String, Object>> dispersionList = microseismDao.queryDispersion1(params);

        // 计算maxW
        maxW = maxW(frequencyRatioList, dispersionList);
    }

    /**
     * 计算历史数据,得到maxW
     *
     * @param frequencyRatioList
     * @param dispersionList
     */
    private int maxW(List<Map<String, Object>> frequencyRatioList, List<Map<String, Object>> dispersionList) {
        final Map<String, Integer> datetimeAndW1 = new HashMap<>();
        final Map<String, Integer> datetimeAndW2 = new HashMap<>();

        int maxW = 0;

        for (int i = 0; i < frequencyRatioList.size(); i++) {
            String datetime = (String) frequencyRatioList.get(i).get("datetime");
            double frequencyRatio = (double) frequencyRatioList.get(i).get("frequencyRatio");
            int w1 = 0, w2 = 0;
            if (frequencyRatio > warningAndV1.get("longWarning")) {
                w1++;
            }
            datetimeAndW1.put(datetime, w1);

            if (frequencyRatio > warningAndV1.get("shortWarning")) {
                w2++;
            }
            datetimeAndW2.put(datetime, w2);
        }

        for (int i = 0; i < dispersionList.size(); i++) {
            String datetime = (String) dispersionList.get(i).get("datetime");
            double dispersion = (double) dispersionList.get(i).get("dispersion");

            Integer w1 = datetimeAndW1.get(datetime);
            Integer w2 = datetimeAndW2.get(datetime);

            if (w1 == null) {
                w1 = 0;
                if (dispersion > warningAndV2.get("longWarning")) {
                    w1++;
                }
                datetimeAndW1.put(datetime, w1);
            } else {
                if (dispersion > warningAndV2.get("longWarning")) {
                    w1++;
                }
                datetimeAndW1.put(datetime, w1);
            }

            if (w2 == null) {
                w2 = 0;
                if (dispersion > warningAndV2.get("longWarning")) {
                    w2++;
                }
                datetimeAndW2.put(datetime, w2);
            } else {
                if (dispersion > warningAndV2.get("shortWarning")) {
                    w2++;
                }
                datetimeAndW2.put(datetime, w2);
            }
            maxW = maxW > (w1 > w2 ? w1 : w2) ? maxW : (w1 > w2 ? w1 : w2);
        }
        return maxW;
    }

    /**
     * 完成一些成员变量的初始化
     *
     * @param studyResult
     */
    private synchronized void initialField(Map<String, Object> studyResult) {

        if (studyResult == null || studyResult.isEmpty()) {
            throw new IllegalArgumentException("遗传算法的学习结果为空.");
        }
        // 长期预警
        longWarningTime = (double) studyResult.get("T2");
        longWarningR = (double) studyResult.get("R2");
        warningAndR.put("longWarning", longWarningR);

        double V1 = (double) studyResult.get("Best2");
        double V2 = (double) studyResult.get("Best3");

        // 短预警
        warningAndV1.put("shortWarning", V1);
        warningAndV2.put("shortWarning", V2);

        V1 = (double) studyResult.get("Best5");
        V2 = (double) studyResult.get("Best6");

        // 长预警
        warningAndV1.put("longWarning", V1);
        warningAndV2.put("longWarning", V2);

        // 短期预警
        shortWarningTime = (double) studyResult.get("T1");
        shortWarningR = (double) studyResult.get("R1");
        warningAndR.put("shortWarning", shortWarningR);
    }
}
